/**
 * Copyright (c) 2013 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners. 
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.composedui.views;

import java.io.IOException;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;

import com.nokia.mid.ui.FileSelect;
import com.nokia.mid.ui.FileSelectDetail;

import com.nokia.example.composedui.ViewManager;
import com.nokia.example.composedui.model.DataItem;
import com.nokia.example.composedui.model.ItemStorage;
import com.nokia.example.composedui.utils.AppDataStorage;
import com.nokia.example.composedui.utils.ImageUtils;
import com.nokia.example.composedui.utils.PersistableState;
import com.nokia.example.composedui.views.elements.Commands;

/**
 * An example Form-based view, which just shows a single text line in the form
 * content area. Implements CommandLister interface to be able to detect back
 * button presses, so it can ask ViewManager to show the previous view.
 */
public class ItemEditView
    extends Form
    implements CommandListener,
               ItemStateListener,
               ItemCommandListener,
               PersistableState,
               ImageUtils.Listener
{
    // Constants
    private static final String STORAGE_ID_FOR_TEXTFIELD_CONTENTS = "editedDataItemName";
    private static final String ITEM_NAME_TEXT_FIELD_HEADER = "Item name";
    private static final String IMAGE_ITEM_HEADER = "Tap to change the image";

    // Members
    private final Command backCommand;
    private final Command saveCommand;
    private ViewManager viewManager;
    private ItemStorage itemStorage;
    private DataItem dataItem;
    private TextField itemNameField;
    private ImageItem imageItem;
    private String imageUri;
    private boolean newItemMode;

    /**
     * Constructor.
     */
    public ItemEditView() {
        super(null);
        setTitle("Edit");
        saveCommand = new Command("Save", Command.SCREEN, 1);
        backCommand = new Command("Back", Command.BACK, 1);
        addCommand(saveCommand);
        addCommand(backCommand);
        setCommandListener(this);
        setItemStateListener(this);
    }

    /**
     * Constructor.
     * @param itemStorage
     * @param viewManager
     */
    public ItemEditView(ItemStorage itemStorage, ViewManager viewManager) {
        this();
        restoreInstance(null, itemStorage, viewManager, null, null);
    }

    /**
     * Constructor.
     * @param dataItem
     * @param itemStorage
     * @param viewManager
     */
    public ItemEditView(DataItem dataItem,
                        ItemStorage itemStorage,
                        ViewManager viewManager)
    {
        this();
        restoreInstance(dataItem, itemStorage, viewManager, null, null);
    }

    /**
     * @see javax.microedition.lcdui.ItemStateListener#itemStateChanged(Item)
     */
    public void itemStateChanged(Item item) {
        if (item.equals(itemNameField)) {
            setTitle("Edit " + itemNameField.getString());
        }
    }

    /**
     * @see javax.microedition.lcdui.ItemCommandListener#commandAction(Command, Item) 
     */
    public void commandAction(Command command, Item item) {
        if (Commands.SELECT.equals(command)) {
            selectNewImage();
        }
    }

    /**
     * @see javax.microedition.lcdui.CommandListener#commandAction(Command, Displayable)
     */
    public void commandAction(Command command, Displayable displayable) {
        if (saveCommand.equals(command)) {
            dataItem.setName(itemNameField.getString(), false);
            
            if (imageUri == null) {
                imageUri = dataItem.getImageFileName();
            }
            
            dataItem.setImageFileName(imageUri);
            
            if (newItemMode) {
                System.out.println("Adding a new element to item storage just now");
                itemStorage.addElement(dataItem);
            }
            
            itemStorage.saveItemsToAppDataStorage(true); // Save changes
            viewManager.goBack();
        }
        else if (backCommand.equals(command)) {
            // Hardware back button was pressed
            viewManager.goBack();
        }
    }

    /**
     * @see PersistableState#restoreInstance(DataItem, ItemStorage, ViewManager, AppDataStorage, String)
     */
    public void restoreInstance(DataItem selectedDataItem,
                                ItemStorage itemStorage,
                                ViewManager viewManager,
                                AppDataStorage appDataStorage,
                                String uniqueId)
    {
        if (selectedDataItem != null) {
            dataItem = selectedDataItem;
            newItemMode = false;
        }
        else {
            dataItem = new DataItem();
            newItemMode = true;
        }
        
        this.viewManager = viewManager;
        this.itemStorage = itemStorage;
        
        if (appDataStorage != null) {
            String editedDataItemName = appDataStorage.valueByKey(
                uniqueId + STORAGE_ID_FOR_TEXTFIELD_CONTENTS);
            
            if (editedDataItemName != null) {
                dataItem.setName(editedDataItemName);
            }
        }
        
        imageUri = dataItem.getImageFileName();
        updateImage();
    }

    /**
     * @see PersistableState#saveInstance(AppDataStorage, String)
     */
    public void saveInstance(AppDataStorage appDataStorage, String uniqueId) {
        appDataStorage.put(uniqueId + STORAGE_ID_FOR_TEXTFIELD_CONTENTS,
                           itemNameField.getString());
    }

    /**
     * @see ImageUtils.Listener#onImageReady(Image)
     */
    public void onImageReady(int requestId, Image image) {
        final int width = getWidth();
        
        try {
            image =
                ImageUtils.pixelMixingScale(image, width,
                    image.getHeight() * width / image.getWidth());
        }
        catch (IllegalArgumentException e) {
        }
        
        if (imageItem == null) {
            createComponents(image);
        }
        else {
            imageItem.setImage(image);
        }
    }

    /**
     * @see ImageUtils.Listener#onGettingImageFailed()
     */
    public void onGettingImageFailed() {
        createComponents(null);
    }

    /**
     * Selects a new image from file system. Note that FileSelect instance has
     * to run in a different thread in order for it to work.
     */
    private void selectNewImage() {
        new Thread(new Runnable() {  
            public void run() {
                try {
                    FileSelectDetail arrayOfSelectedFiles[] =
                        FileSelect.launch(
                            FileSelect.FILE_SYSTEM_ALL,
                            FileSelect.MEDIA_TYPE_PICTURE, 
                            false // Select only one item at a time
                        );
                    
                    if (arrayOfSelectedFiles == null
                        || arrayOfSelectedFiles.length == 0)
                    {
                        // If user goes back without selecting a file
                        return;
                    }
                    
                    imageUri = arrayOfSelectedFiles[0].url;
                    updateImage();
                }
                catch (IOException ioe) {
                    ioe.printStackTrace();
                }
                catch (IllegalArgumentException iae) {
                    iae.printStackTrace();
                }
                catch (SecurityException se) {
                    se.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * Updates the displayed image.
     */
    private synchronized void updateImage() {
        Image image = ImageUtils.getImage(imageUri);
        
        if (image == null) {
            ImageUtils.getImageAsync(imageUri,
                ImageUtils.DO_NOT_SCALE, ImageUtils.DO_NOT_SCALE, this);
        }
        else {
            onImageReady(0, image);
        }
    }

    /**
     * Creates the UI components and appends them into the view.
     */
    private void createComponents(final Image image) {
        deleteAll();
        
        setTitle("Edit " + dataItem.getName());
        
        itemNameField =
            new TextField(ITEM_NAME_TEXT_FIELD_HEADER,
                dataItem.getName(), 128, TextField.ANY);
        append(itemNameField);
        
        imageItem = new ImageItem(IMAGE_ITEM_HEADER, image, Item.LAYOUT_DEFAULT, "");
        imageItem.setDefaultCommand(Commands.SELECT);
        imageItem.setItemCommandListener(this);
        append(imageItem);
    }
}
